/*
 * @Author: CSG@HYC
 * @Date: 2025-07-29 10:17:46
 * @FilePath: \MDK-ARMe:\Desktop\F4_template\HW\Src\eth.c
 */
#include "eth.h"
#include "uart.h"


ETH_HandleTypeDef heth;

/* Ethernet RX DMA Descriptor */
__ALIGN_BEGIN ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END;

/* Ethernet TX DMA Descriptor */
__ALIGN_BEGIN ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END;

/* Ethernet Receive Buffer */
__ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END;

/* Ethernet Transmit Buffer */
__ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END;


// Callback function, Call in HAL_ETH_Init function
void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
{
    // 在MspInit中负责底层的GPIO初始化以及开启时钟
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if (heth->Instance == ETH)
    {
        /**
         * ETH GPIO Configuration
         * PA1    ETH_REF_CLK    PP
         * PA2    ETH_MDIO       PP
         * PA7    ETH_CRS_DV     PP
         * PC1    ETH_MDC        PP
         * PC4    ETH_RXD0       PP
         * PC5    ETH_RXD1       PP
         * PG11   ETH_TX_EN      PP
         * PG13   ETH_TXD0       PP
         * PG14   ETH_TXD1       PP
         */
        // Enable Clock
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_GPIOC_CLK_ENABLE();
        __HAL_RCC_GPIOG_CLK_ENABLE();
        __HAL_RCC_ETH_CLK_ENABLE();
        __HAL_RCC_DMA2_CLK_ENABLE();
        

        // Configuration GPIO
        GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

        GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
        HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

        // Configuration NVIC
        HAL_NVIC_SetPriority(ETH_IRQn, 6, 0);
        HAL_NVIC_EnableIRQ(ETH_IRQn);
    }
    
}

HAL_StatusTypeDef HW_ETH_Init(void)
{
    HAL_StatusTypeDef ret;

    uint8_t MACAddr[6];     // MAC Address
    HAL_ETH_DeInit(&heth);  // DeInit ETH Peripheral

    ETH->DMABMR |= ETH_DMABMR_SR;   // 软复位DMA

    /* Init ETH */
    MACAddr[0] = 0x02;
    MACAddr[1] = 0x00;
    MACAddr[2] = 0x00;
    MACAddr[3] = 0x00;
    MACAddr[4] = 0x00;
    MACAddr[5] = 0x00;

    heth.Instance = ETH;
    /* 是否启用物理层速度自动自适应模式10/100M自适应 */
    heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
    heth.Init.Speed = ETH_SPEED_100M;
    heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
    heth.Init.PhyAddress = LAN8720_PHY_ADDRESS;
    heth.Init.MACAddr = &MACAddr;
    /* 选择以太网数据接收模式 ：轮询模式(ETH_RXPOLLING_MODE)or中断模式(ETH_RXINTERRUPT_MODE) */
    heth.Init.RxMode = ETH_RXPOLLING_MODE;
    /* 选择校验模式 ：硬件校验(ETH_CHECKSUM_BY_HARDWARE)or软件校验(ETH_CHECKSUM_BY_SOFTWARE) */
    heth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
    heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;

    ret = HAL_ETH_Init(&heth);

    if (ret != HAL_OK)
    {
        return ret;
    }
    
    /* Initiakize Tx Descriptors list : Chain Mode */
    HAL_ETH_DMATxDescListInit(&heth, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
    /* Initiakize Rx Descriptors list : Chain Mode */
    HAL_ETH_DMATxDescListInit(&heth, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);

    return HAL_OK;

}

void ETH_IRQHandler(void)
{
    HAL_ETH_IRQHandler(&heth);
}

void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{
    // if (heth->Instance == ETH)
    // {
    //     /* code */
    // }  
}

void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth)
{

}


//uint32_t sys_now(void)
//{
//    return HAL_GetTick();  // 返回系统当前毫秒
//}

//uint32_t sys_jiffies(void)
//{
//    return sys_now();  
//}

uint32_t lwip_port_rand(void)
{
    return HAL_GetTick() ^ 0x5A5A5A5A; 
}

void lwip_example_app_platform_assert(const char *msg, int line)
{
    printf("LWIP Assert: %s at line %d\r\n", msg, line);
    while (1);
}

void sio_open(void) {}
void sio_tryread(void) {}
void sio_send(void) {}
